package com.example.gaussdb;

//DBtest.java
//https://support.huaweicloud.com/centralized-devg-v3-gaussdb/gaussdb-12-0066.html
//演示基于JDBC开发的主要步骤，会涉及创建数据库、创建表、插入数据等。
// 认证用的用户名和密码直接写到代码中有很大的安全风险，建议在配置文件或者环境变量中存放（密码应密文存放，使用时解密），确保安全。
// 本示例以用户名和密码保存在环境变量中为例，运行本示例前请先在本地环境中设置环境变量（环境变量名称请根据自身情况进行设置）EXAMPLE_USERNAME_ENV和EXAMPLE_PASSWORD_ENV。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.CallableStatement;
import java.sql.Types;

public class GaussTest {


    //创建数据库连接。
    public static Connection GetConnection(String username, String passwd) {
//        String driver = "org.postgresql.Driver";
        String driver = "com.huawei.opengauss.jdbc.Driver";
        String sourceURL = "jdbc:opengauss://1.92.87.37:8000/postgres";
//        String sourceURL = "jdbc:opengauss://10.13.10.21:8000/postgres";
//        String sourceURL = "jdbc:opengauss://10.13.224.11:8000/postgres";
        Connection conn = null;
        try {
            //加载数据库驱动。
            Class.forName(driver).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        try {
            //创建数据库连接。
            conn = DriverManager.getConnection(sourceURL, username, passwd);
            System.out.println("Connection succeed!");
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        return conn;
    };

    //执行普通SQL语句，创建customer_t1表。
    public static void CreateTable(Connection conn) {
        Statement stmt = null;
        try {
            stmt = conn.createStatement();

            //执行普通SQL语句。
            int rc = stmt
                    .executeUpdate("CREATE TABLE test(id INTEGER, name VARCHAR(32));");

            stmt.close();
        } catch (SQLException e) {
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
            }
            e.printStackTrace();
        }
    }

    //执行预处理语句，批量插入数据。
    public static void BatchInsertData(Connection conn) {
        PreparedStatement pst = null;

        try {
            //生成预处理语句。
            pst = conn.prepareStatement("INSERT INTO customer_t1 VALUES (?,?)");
            for (int i = 0; i < 3; i++) {
                //添加参数。
                pst.setInt(1, i);
                pst.setString(2, "data " + i);
                pst.addBatch();
            }
            //执行批处理。
            pst.executeBatch();
            pst.close();
        } catch (SQLException e) {
            if (pst != null) {
                try {
                    pst.close();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
            }
            e.printStackTrace();
        }
    }

    //执行预编译语句，更新数据。
    public static void ExecPreparedSQL(Connection conn) {
        PreparedStatement pstmt = null;
        try {
            pstmt = conn
                    .prepareStatement("UPDATE customer_t1 SET c_customer_name = ? WHERE c_customer_sk = 1");
            pstmt.setString(1, "new Data");
            int rowcount = pstmt.executeUpdate();
            pstmt.close();
        } catch (SQLException e) {
            if (pstmt != null) {
                try {
                    pstmt.close();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
            }
            e.printStackTrace();
        }
    }

    //新建存储过程。
    public static void CreateCallable(Connection conn) {
        Statement stmt = null;
        try {
            stmt = conn.createStatement();
            // 新建函数，返回三个输入值的和。
            stmt.execute("create or replace procedure testproc \n" +
                    "(\n" +
                    "    psv_in1 in integer,\n" +
                    "    psv_in2 in integer,\n" +
                    "    psv_inout inout integer\n" +
                    ")\n" +
                    "as\n" +
                    "begin\n" +
                    "    psv_inout := psv_in1 + psv_in2 + psv_inout;\n" +
                    "end;\n" +
                    "/");
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    //执行存储过程。
    public static void ExecCallableSQL(Connection conn) {
        CallableStatement cstmt = null;
        try {
            // 存储过程TESTPROC需提前创建。
            cstmt=conn.prepareCall("{? = CALL TESTPROC(?,?,?)}");
            cstmt.setInt(2, 50);
            cstmt.setInt(1, 20);
            cstmt.setInt(3, 90);
            cstmt.registerOutParameter(4, Types.INTEGER);  //注册out类型的参数，类型为整型。
            cstmt.execute();
            int out = cstmt.getInt(4);  //获取out参数
            System.out.println("The CallableStatment TESTPROC returns:"+out);
            cstmt.close();
        } catch (SQLException e) {
            if (cstmt != null) {
                try {
                    cstmt.close();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
            }
            e.printStackTrace();
        }
    }


    /**
     * 主程序，逐步调用各静态方法。
     * @param args
     */
    public static void main(String[] args) {
        //创建数据库连接。
//        String userName = System.getenv("root");
//        String password = System.getenv("Esign@123456");
        Connection conn = GetConnection("root", "Cebsz@#95595");

        //创建表。
        CreateTable(conn);

        //批插数据。
//        BatchInsertData(conn);

        //执行预编译语句，更新数据。
//        ExecPreparedSQL(conn);

        //新建存储过程。
//        CreateCallable(conn);

        //执行存储过程。
//        ExecCallableSQL(conn);

        //关闭数据库连接。
        try {
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }

}
